package com.mall.user.services;

import com.alibaba.fastjson.JSON;
import com.mall.commons.tool.utils.CookieUtil;
import com.mall.user.ILoginService;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.converter.UserConverterMapper;
import com.mall.user.dal.entitys.Member;
import com.mall.user.dal.persistence.MemberMapper;
import com.mall.user.dto.CheckAuthRequest;
import com.mall.user.dto.CheckAuthResponse;
import com.mall.user.dto.UserLoginRequest;
import com.mall.user.dto.UserLoginResponse;
import com.mall.user.utils.ExceptionProcessorUtils;
import com.mall.user.utils.JwtTokenUtils;
import jodd.util.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import tk.mybatis.mapper.entity.Example;

import javax.xml.crypto.dsig.keyinfo.RetrievalMethod;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description:
 * @autyor:caicaicai
 */
@Slf4j
@Component//注册组件
@Service//注册微服务
public class LoginServiceImpl implements ILoginService {

    @Autowired
    MemberMapper memberMapper;

    @Autowired
    UserConverterMapper userConverterMapper;

    @Override
    public UserLoginResponse login(UserLoginRequest loginRequest) {
        UserLoginResponse loginResponse = new UserLoginResponse();
        //1.验证用户名和密码（查表：唯一用户名查询密码是否存在，再判断用户是否激活，最后判断密码是否相等）
        //todo 抛出的异常如何处理
        try {
            loginRequest.requestCheck();//基础校验
        } catch (Exception e) {
            ExceptionProcessorUtils.wrapperHandlerException(loginResponse, e);
            loginResponse.setCode(SysRetCodeConstants.REQUISITE_PARAMETER_NOT_EXIST.getCode());
            loginResponse.setMsg(SysRetCodeConstants.REQUISITE_PARAMETER_NOT_EXIST.getMessage());
            return loginResponse;
        }

        Example example = new Example(Member.class);
        example.createCriteria().andEqualTo("username", loginRequest.getUserName());
        List<Member> members = memberMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(members)){
            //username不存在/用户名或密码错误
            log.error("验证用户名和密码 之 该用户名不存在");
            loginResponse.setCode(SysRetCodeConstants.USERORPASSWORD_ERRROR.getCode());
            loginResponse.setMsg(SysRetCodeConstants.USERORPASSWORD_ERRROR.getMessage());
            return loginResponse;
        }
        Member member = members.get(0);
        log.error(members.toString());

        //判断用户是否激活
        if(member.getIsVerified().equals("N")){
            //未激活
            log.error("验证用户名和密码 之 该用户名未激活");
            loginResponse.setCode(SysRetCodeConstants.USER_ISVERFIED_ERROR.getCode());
            loginResponse.setMsg(SysRetCodeConstants.USER_ISVERFIED_ERROR.getMessage());
            return loginResponse;
        }

        //判断密码是否一致
        //将前端传来的密码用同样的方法加密，再判断和数据库中存储的密码是否相等
        String userPwd = DigestUtils.md5DigestAsHex(loginRequest.getPassword().getBytes());
        if(!userPwd.equals(member.getPassword())){
            //密码不一致
            log.error("验证用户名和密码 之 该用户名存在且激活，但密码输入错误；密码={}，输入密码={}", member.getPassword(), userPwd);
            loginResponse.setCode(SysRetCodeConstants.USERORPASSWORD_ERRROR.getCode());
            loginResponse.setCode(SysRetCodeConstants.USERORPASSWORD_ERRROR.getMessage());
            return loginResponse;
        }

        //2.生成JWT token
        //工具类：map --> 字符串msg --> 加密成token
        Map map = new HashMap<String, Object>();
        map.put("uid", member.getId());//id Long类型
        map.put("file", member.getFile());//file头像 String类型
        map.put("username", member.getUsername());//username String类型
        String token = JwtTokenUtils.builder().msg(JSON.toJSONString(map)).build().creatJwtToken();
        log.info("验证用户名和密码 后 生成token={}", token);

        //传递给controller层
        loginResponse = userConverterMapper.converter(member);
        log.error(loginResponse.toString());
        loginResponse.setToken(token);
        loginResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
        loginResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return loginResponse;
    }

    /**
     * 验证token
     * @param checkAuthRequest
     * @return
     */
    @Override
    public CheckAuthResponse validToken(CheckAuthRequest checkAuthRequest) {
        String RequestToken = checkAuthRequest.getToken();
        //解密
        String token = JwtTokenUtils.builder().token(RequestToken).build().freeJwt();
        //todo 如何判断token是否正确 token又是什么，直接是userinfo么？？

        CheckAuthResponse checkAuthResponse = new CheckAuthResponse();
        checkAuthResponse.setUserinfo(token);
        checkAuthResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
        checkAuthResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return checkAuthResponse;
    }
}
